//
// Created on 2024/8/29.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef AVCODECSAMPLE_OPENGL_PLAYER_H
#define AVCODECSAMPLE_OPENGL_PLAYER_H

#include <bits/alltypes.h>
#include <mutex>
#include <memory>
#include <atomic>
#include <thread>
#include <unistd.h>
#include <ohaudio/native_audiorenderer.h>
#include <ohaudio/native_audiostreambuilder.h>
#include <fstream>
#include "video_decoder.h"
#include "audio_decoder.h"
#include "multimedia/player_framework/native_avbuffer.h"
#include "demuxer.h"
#include "sample_info.h"
#include "plugin_manager.h"

class Player {
public:
    Player(){};
    ~Player();
    
    static Player& GetInstance()
    {
        static Player player;
        return player;
    }

    int32_t Init(SampleInfo &sampleInfo);
    int32_t Start();
    int32_t Pause();
    int32_t Resume();
    int32_t Loop(bool loopFlag);
    int32_t Seek(int64_t position);
    int32_t Kill();
    int32_t WaitForDone();

private:
    void VideoDecInputThread();
    void VideoDecOutputThread();
    void AudioDecInputThread();
    void AudioDecOutputThread();
    void Release();
    void StartRelease();
    void ReleaseThread();
    int32_t CreateAudioDecoder();
    int32_t CreateVideoDecoder();

    std::unique_ptr<VideoDecoder> videoDecoder_ = nullptr;
    std::shared_ptr<AudioDecoder> audioDecoder_ = nullptr;
    std::unique_ptr<Demuxer> demuxer_ = nullptr;
    
    std::mutex mutex_;
    std::atomic<bool> isLoop_ { false };
    std::atomic<bool> isStarted_ { false };
    std::atomic<bool> isPause_ { false };
    std::unique_ptr<std::thread> videoDecInputThread_ = nullptr;
    std::unique_ptr<std::thread> videoDecOutputThread_ = nullptr;
    std::unique_ptr<std::thread> audioDecInputThread_ = nullptr;
    std::unique_ptr<std::thread> audioDecOutputThread_ = nullptr;
    std::unique_ptr<std::thread> releaseThread_ = nullptr;
    std::condition_variable doneCond_;
    SampleInfo sampleInfo_;
    CodecUserData *videoDecContext_ = nullptr;
    CodecUserData *audioDecContext_ = nullptr;
    OH_AudioStreamBuilder* builder_ = nullptr;
    OH_AudioRenderer* audioRenderer_ = nullptr;
#ifdef DEBUG_DECODE
    std::ofstream audioOutputFile_; // for debug
#endif
    static constexpr int64_t MICROSECOND = 1000000;
    static constexpr int64_t MILLISECOND = 1000;
};

#endif //AVCODECSAMPLE_OPENGL_PLAYER_H
